package gov.child.entities.vo;

import gov.child.entities.vo.annotation.Alias;
import gov.child.entities.vo.annotation.IgnoreField;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.Collection;
import java.util.regex.Pattern;

import static gov.child.util.AnnotationHelper.unAnnotatedFields;

/**
 * @author fzh
 * @since 2017/9/12
 */
public final class BeanTransformer {
    /**
     * Bean转换工具，源对象为src，转换为T类型的对象。 src包含的Field要包含des的Field
     *
     * @param des 目标对象Class
     * @return 目标对象
     */
    public static <T> T transform(Class<T> des, Object... objs) {
        for (Object obj: objs) {
            Objects.requireNonNull(obj, "Here objects have a null pointer.");
        }
        T t;
        try {
            t = des.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException("Create instance of " + des.getName() + " failed. ");
        }
        Collection<Field> fields;
        for (Object obj : objs) {
            fields = unAnnotatedFields(obj.getClass(), IgnoreField.class);
            Field f;
            String fieldName = null;
            try {
                for (Field field : fields) {
                    // f 为 des对应在 obj里面的域
                    if (Modifier.isStatic(field.getModifiers())) continue;
                    if (field.isAnnotationPresent(Alias.class)) {
                        Alias alias = field.getAnnotation(Alias.class);
                        fieldName = alias.value();
                    } else fieldName = field.getName();
                    // throw NoSuchFieldException
                    f = des.getDeclaredField(fieldName);
                    field.setAccessible(true);
                    f.setAccessible(true);
                    f.set(t, field.get(obj));
                }
            } catch (NoSuchFieldException | IllegalAccessException e) {
                throw new RuntimeException(des.getName() + " not have a field named as " + fieldName);
            }
        }
        return t;
    }
    public static <T> List parseFrom(Class<T> tcls, List<?> objects){
        if (objects == Collections.EMPTY_LIST) return objects;
        List<T> list = new ArrayList<>();
        objects.forEach(o -> {
            list.add(transform(tcls, o));
        });
        return list;
    }
}